﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AtDevice
{
    /// <summary>
    /// Utility class to build AT commands.
    /// </summary>
    /// <example>
    /// To build a simple request (eg. "AT+CPBS?").
    /// <code>
    /// new AtCommand("CPBS").Request()
    /// </code>
    /// </example>
    public class AtCommand
    {
        private string _command;

        /// <summary>
        /// Construct new builder for the specified command.
        /// </summary>
        /// <param name="commandName"></param>
        public AtCommand(string commandName):
            this(commandName, false)
        {
        }
        
        /// <summary>
        /// Construct new builder for the specified command.
        /// </summary>
        /// <param name="commandName"></param>
        /// <param name="extension">If true, using "AT^" format (for non-standard commands)</param>
        public AtCommand(string commandName, bool extension)
        {
            if(extension)
                _command = String.Format("AT^{0}=", commandName);
            else
                _command = String.Format("AT+{0}=", commandName);
        }

        /// <summary>
        /// Append a question mark to the command to make a short request. Eg. "AT+CBPS?"
        /// </summary>
        public AtCommand Request()
        {
            if(_command[_command.Length-1] == '=')
            {
                TrimEnd();
                _command += "?";
            }
            else
            {
                throw new InvalidOperationException("Request must be called right after constructor");
            }

            return this;
        }

        /// <summary>
        /// Append a question mark to the command to make a long request. Eg. "AT+CBPS=?"
        /// </summary>
        public AtCommand LongRequest()
        {
            if(_command[_command.Length-1] == '=')
                _command += "?";
            else
                throw new InvalidOperationException("Request must be called right after constructor");

            return this;
        }

        /// <summary>
        /// Append a string to the AT command.
        /// </summary>
        public AtCommand AppendString(string value)
        {
            _command = String.Format("{0}\"{1}\",", _command, value);
            return this;
        }

        /// <summary>
        /// Append a comma to the command.
        /// </summary>
        public AtCommand AppendEmptyContent()
        {
            _command += ",";
            return this;
        }

        /// <summary>
        /// Append an integer to the AT command.
        /// </summary>
        public AtCommand AppendInt(int value)
        {
            _command = String.Format("{0}{1},", _command, value);
            return this;
        }

        /// <summary>
        /// Append a Ctrl+Z terminated message to the AT command.
        /// </summary>
        public AtCommand AppendMessage(string message)
        {
            _command = _command.TrimEnd(new char[] { ',' });
            _command = String.Format("{0}\r{1}\n\x1A\x1B", _command, message);
            return this;
        }

        /// <summary>
        /// Get the actual AT command after it has been built.
        /// </summary>
        public override string ToString()
        {
            TrimEnd();
            return _command + "\r";
        }

        private void TrimEnd()
        {
            _command = _command.TrimEnd(new char[] { ',', '=', '+' });
        }
    }
}
